#implement support for "strict" checks, i.e. checks where attributes and tags are both assayed
#implement support for mutiple gold standards with links
#decompose buildSubjectList
#make kappa a class that can be referenced text-by-text? maintain separate Pi and Pe for each text, then
#	add them all together at the end???

import xml.etree.ElementTree as ET
import re, os, sys
from MAESubject import *
from MAEStats import *

class maeParser:
	"""Parser class to extract metadata from annotations"""
	def __init__(self, files, annots = [], phases = [], tagnames = [], anpattern = r'-[Aa][0-9]*[-\.]', ppattern = r'-[Pp][0-9]*[\.-]'):
		try:
			self.filenames = [os.path.join(files, fname) for direc,subdirec,files in os.walk(direct) for direct in open(files).readlines() for fname in files if fname[-3:] == 'xml']
		except UnboundLocalError:
			self.filenames = [os.path.join(files, fname) for direc,subdirec,fnames in os.walk(files) for fname in fnames if fname[-3:] == 'xml']
		except:
			print "Incorrect path name."
			raise
		self.anpattern = anpattern
		self.ppattern = ppattern
		self.phases = [p.lower() for p in phases]
		self.tagnames = tagnames
		self.annots = bool(annots) and annots or sorted(list(set([re.search(anpattern, fname).group().strip('-.').upper() for fname in self.filenames if re.search(anpattern, fname)])))
		
	def getAnnotators(self):
		"""Returns a list of annotators from the corpus"""
		return self.annots
		
	def getTagNodes(self, filename):
		"""Acquires tags from a given file"""
		return [node for li in ET.parse(filename).getroot().getchildren() if li.tag == 'TAGS' for node in li.getchildren()]
		
	def buildSubjectList(self, mode = "extent", golds = []):
		"""Returns a list of extents or links occurring in the corpus"""
		subj, attset, comp = ((re.match(r'[Ee](xtent)?', mode) and (extent, set(['start', 'end', 'text']), (mode[-6:] == "_loose" and extent.overlaps or extent.__eq__)) or (link, set(['fromID', 'toID']), link.__eq__)))
		li = []
		annots = self.getAnnotators()
		golds = [hash(ET.parse(fname).getroot().getchildren()[0].text) for fname in golds]
		try:
			if len(annots) < 1 or (subj == link and not golds):
				raise AnnotError
			if subj == link and not golds:
				raise GoldError
		except AnnotError as A:
			print A
		except GoldError as G:
			print G
		for fname in self.filenames:
			if not re.search(self.anpattern, fname):
				break
			annot = re.search(self.anpattern, fname).group().strip('-.').upper()
			thash = hash(ET.parse(fname).getroot().getchildren()[0].text)
			if annot in annots and (not self.phases or (re.search(self.ppattern, fname) and (re.search(self.ppattern, fname).group().strip('-.').lower() in self.phases))):
				for i in self.getTagNodes(fname):
					if attset.issubset(set(i.attrib.keys())):
						tempsub = subj(annots, i, fname, thash)
						if ((subj == extent) and not (all([tempsub.data[j] == -1 for j in ['start', 'end']]))) or (subj == link and tempsub.thash in golds):
							for sbj in li:
								if comp(tempsub, sbj):
									sbj.add_annot(annot, i)
									break
							else:
								tempsub.add_annot(annot, i)
								li.append(tempsub)
		if self.tagnames:
			li = [subj for subj in li if set(self.tagnames).intersection(set(subj.getTags().values()))]
		return li
